package controllers;

import java.util.Date;
import java.util.List;

import models.Category;
import models.Deal;
import models.User;
import play.data.validation.Valid;
import play.db.jpa.GenericModel.JPAQuery;
import play.i18n.Lang;
import play.i18n.Messages;
import play.libs.Crypto;
import play.mvc.Before;
import play.mvc.Controller;

/**
 * This is the main application controller This can be used as base class in
 * case the workflow needs the logged-in user
 * 
 */
public class Application extends Controller {

	/**
	 * This method is run before calling any method of the class It basically
	 * gets the user and the categories for the pages to render them accordingly
	 * (since most of the pages need it)
	 */
	@Before
	static void preProcess() {
		String lang = request.params.get("lang");
		if (null != lang) {
			Lang.change(lang);
		}

		User user = connected();
		if (user != null) {
			renderArgs.put("user", user);
		}

		// render the categories
		List<Category> categories = Category.findAll();
		if (null != categories && categories.size() > 0) {
			renderArgs.put("categories", categories);
		}
	}

	public static void changeLang(String lang) {
		index();
	}

	/**
	 * This method checks if the user is logged in and returns the instace of
	 * the user object
	 * 
	 * @return The User object of the logged-in user
	 */
	static User connected() {
		if (renderArgs.get("user") != null) {
			return renderArgs.get("user", User.class);
		}
		String username = session.get("user");
		if (username != null) {
			return User.find("byUsername", username).first();
		}
		return null;
	}

	/**
	 * Handle the main page
	 */
	public static void index() {
		JPAQuery query = Deal
				.find("select distinct d from Deal d, Address a where d.address = a.id and d.endDate >= ? order by d.endDate asc limit 10",
						new Date());
		List<Object> deals = query.fetch();
		render(deals);
	}

	/**
	 * My deals page
	 */
	public static void myDeals() {
		if (connected() != null) {
			DealsAdmin.index();
		}
		renderArgs.put("ignoreCategory", true);
		render();
	}

	/**
	 * Requesting the register page
	 */
	public static void register() {
		List<Category> categories = Category.findAll();
		renderArgs.put("ignoreCategory", true);
		render(categories);
	}

	/**
	 * Register user (POST) i.e save user workflow
	 * 
	 * @param user
	 * @param verifyPassword
	 */
	public static void saveUser(@Valid User user, String verifyPassword) {

		// validation checks if the entered data is correct and
		// the password and the verifyPassword field matches
		validation.required(verifyPassword);
		validation.equals(verifyPassword, user.password).message("user.validation.password.nomatch");
		if (validation.hasErrors()) {
			render("@register", user, verifyPassword);
		}

		// MD5 hash the password
		user.password = Crypto.passwordHash(user.password);
		user.create();
		session.put("user", user.username);
		flash.success(Messages.get("login.success.welcome", user.name));
		DealsAdmin.index();
	}

	/**
	 * Login requested by providing the username and passwor
	 * 
	 * @param username
	 * @param password
	 */
	public static void login(String username, String password) {
		// MD5 has the password before comparison
		User user = User.find("byUsernameAndPassword", username, Crypto.passwordHash(password)).first();
		if (user != null) {
			session.put("user", user.username);
			flash.success(Messages.get("login.success.welcome", user.name));
			DealsAdmin.index();
		}
		flash.put("username", username);
		flash.error(Messages.get("login.failed"));
		myDeals();
	}

	/**
	 * Logout
	 */
	public static void logout() {
		// cleare the sessoin variable
		session.clear();
		myDeals();
	}

	/**
	 * Get the company details page
	 */
	public static void company() {
		render();
	}

}